package xyz.zhzby.cyzx.judge.core;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import xyz.zhzby.cyzx.judge.entity.Submission;

import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zby
 * @date 2022/02/04
 * @Description 程序编译器, 用于编译用户提交的代码.
 */
@Component
@Slf4j
public class Compiler {

    @Autowired
    private xyz.zhzby.cyzx.judge.core.Runner compilerRunner;

    /**
     * @Param [submission, workDirectory, baseFileName] [提交记录对象, 编译输出目录, 编译输出文件名]
     * @Return java.util.Map<java.lang.String, java.lang.Object> [包含编译输出结果的Map<String, Object>对象]
     * @Author zby
     * @Date 2022/02/04
     * @Description 获取编译输出结果.
     */
    public Map<String, Object> getCompileResult(Submission submission, String workDirectory, String baseFileName) {
        String commandLine = getCompileCommandLine(submission, workDirectory, baseFileName);
        String compileLogPath = getCompileLogPath(workDirectory, baseFileName);
        return getCompileResult(commandLine, compileLogPath);
    }

    /**
     * @Param [submission, workDirectory, baseFileName] [提交记录对象, 编译输出目录, 编译输出文件名]
     * @Return java.lang.String [编译命令]
     * @Author zby
     * @Date 2022/02/04
     * @Description 获取编译命令.
     */
    private String getCompileCommandLine(Submission submission, String workDirectory, String baseFileName) {
        String filePathWithoutExtension = String.format("%s/%s", workDirectory, baseFileName);
        return submission.getLanguage().getCompileCommand().replaceAll("\\{filename}", filePathWithoutExtension);
    }

    /**
     * @Param [workDirectory, baseFileName] [编译输出目录, 编译输出文件名]
     * @Return java.lang.String [编译日志输出的文件路径]
     * @Author zby
     * @Date 2022/02/04
     * @Description 获取编译日志输出的文件路径.
     */
    private String getCompileLogPath(String workDirectory, String baseFileName) {
        return String.format("%s/%s-compile.log", workDirectory, baseFileName);
    }

    /**
     * @Param [commandLine, compileLogPath] [编译命令, 编译日志输出路径]
     * @Return java.util.Map<java.lang.String, java.lang.Object> [包含编译输出结果的Map<String, Object>对象]
     * @Author zby
     * @Date 2022/02/04
     * @Description 获取编译输出结果.
     */
    private Map<String, Object> getCompileResult(String commandLine, String compileLogPath) {
        String inputFilePath = null;
        int timeLimit = 5000;
        int memoryLimit = 0;

        log.info("Start compiling with command: " + commandLine);
        Map<String, Object> runningResult =
                compilerRunner.getRuntimeResult(commandLine, inputFilePath, compileLogPath, timeLimit, memoryLimit);
        Map<String, Object> result = new HashMap<>(3, 1);

        boolean isSuccessful = false;
        if (runningResult != null) {
            int exitCode = (Integer) runningResult.get("exitCode");
            isSuccessful = exitCode == 0;
        }
        result.put("isSuccessful", isSuccessful);
        result.put("log", getCompileOutput(compileLogPath));
        return result;
    }

    /**
     * @Param [compileLogPath] [编译日志路径]
     * @Return java.lang.String [编译日志内容]
     * @Author zby
     * @Date 2022/02/04
     * @Description 获取编译日志内容.
     */
    private String getCompileOutput(String compileLogPath) {
        FileInputStream inputStream;
        String compileLog = "";
        try {
            inputStream = new FileInputStream(compileLogPath);
            compileLog = IOUtils.toString(inputStream, Charset.forName("GB2312"));
            inputStream.close();
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
        return compileLog;
    }

}
